package prolog.terms

abstract class Term extends AnyRef with Cloneable {
  def ref = this
  def bind_to(that: Term, trail: Trail): Boolean

  def unify(that: Term, trail: Trail): Boolean

  /**
   * Defines the reaction to an agent recursing
   * over the structure of a term. <b>This</b> is passed
   * to the agent and the result of the action is returned.
   * Through overriding, for instance, a Fun term will provide
   * the recursion over its arguments, by applying the action
   * to each of them.
   *
   * @see Fun
   */
  def reaction(agent: Term): Term = agent.action(this)

  /**
   * Identity action.
   */
  def action(that: Term): Term = that

  def copy = reaction(new Copier())

  /*
  def matching_copy(that: Term): Option[Term] = {
    val trail = new Trail();
    val ok = unify(that, trail);
    val res = if (ok) Some(that.copy()) else None
    trail.unwind(0)
    res
  }
  */

  final def matches(that: Term, trail: Trail): Boolean = {
    val oldtop = trail.size
    val ok = unify(that, trail)
    trail.unwind(oldtop)
    ok
  }

  final def exec() = -1
  def exec(p: Prog) = -1

}

object Term {
  final def copyList(ts: List[Term]): List[Term] =
    {
      val copier = new Copier()
      ts.map(t => t.reaction(copier))
    }

}